package com.qys.livesMall.shop.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qys.livesMall.common.exception.QysException;
import com.qys.livesMall.shop.mapper.H2ShopBaseMapper;
import com.qys.livesMall.shop.mapper.ShopScoreMapper;
import com.qys.livesMall.shop.modal.dto.shop.ShopScoreDTO;
import com.qys.livesMall.shop.modal.entity.H2ShopBase;
import com.qys.livesMall.shop.modal.entity.ShopScore;
import com.qys.livesMall.shop.modal.vo.ShopScoreVO;
import com.qys.livesMall.shop.service.ShopScoreService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * 店铺评分表(ShopScore)表服务实现类
 *
 * @author makejava
 * @since 2023-08-24 15:54:04
 */
@Service("shopScoreService")
public class ShopScoreServiceImpl extends ServiceImpl<ShopScoreMapper, ShopScore> implements ShopScoreService {

    @Resource
    private H2ShopBaseMapper h2ShopBaseMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void setMark(ShopScoreDTO dto) {

        H2ShopBase shopBase = h2ShopBaseMapper.selectById(dto.getShopId());
        if(shopBase == null){
            throw new QysException("shopId error");
        }

        //商品体验分数
        BigDecimal productScore = dto.getProductScore();
        //物流体验分数
        BigDecimal logisticsScore = dto.getLogisticsScore();
        //售后服务分数
        BigDecimal afterSaleScore = dto.getAfterSaleScore();
        //咨询体验分数
        BigDecimal consultScore = dto.getConsultScore();

        ShopScore score = baseMapper.selectOne(Wrappers.<ShopScore>lambdaQuery().eq(ShopScore::getShopId, dto.getShopId()));
        if(score == null){
            ShopScore shopScore  = new ShopScore();
            BeanUtils.copyProperties(dto, shopScore);
            BigDecimal total = productScore.add(logisticsScore).add(afterSaleScore).add(consultScore);
            BigDecimal averageScore = total.divide(BigDecimal.valueOf(4), 2, RoundingMode.DOWN);
            shopScore.setAverageScore(averageScore);
            shopScore.setPeopleNumber(1);
            save(shopScore);
            //更新店铺表分数
            H2ShopBase h2ShopBase = new H2ShopBase();
            h2ShopBase.setId(dto.getShopId());
            h2ShopBase.setMark(averageScore);
            h2ShopBaseMapper.updateById(h2ShopBase);
        } else {
            Integer oldPeopleNumber = score.getPeopleNumber();
            int newPeopleNumber = oldPeopleNumber + 1;
            BigDecimal newProductScore = score.getProductScore().multiply(new BigDecimal(oldPeopleNumber)).add(dto.getProductScore()).divide(BigDecimal.valueOf(newPeopleNumber), 2, RoundingMode.DOWN);
            BigDecimal newLogisticsScore = score.getLogisticsScore().multiply(new BigDecimal(oldPeopleNumber)).add(dto.getLogisticsScore()).divide(BigDecimal.valueOf(newPeopleNumber), 2, RoundingMode.DOWN);
            BigDecimal newAfterSaleScore = score.getAfterSaleScore().multiply(new BigDecimal(oldPeopleNumber)).add(dto.getAfterSaleScore()).divide(BigDecimal.valueOf(newPeopleNumber), 2, RoundingMode.DOWN);
            BigDecimal newConsultScore = score.getConsultScore().multiply(new BigDecimal(oldPeopleNumber)).add(dto.getConsultScore()).divide(BigDecimal.valueOf(newPeopleNumber), 2, RoundingMode.DOWN);
            score.setPeopleNumber(newPeopleNumber);
            score.setProductScore(newProductScore);
            score.setLogisticsScore(newLogisticsScore);
            score.setAfterSaleScore(newAfterSaleScore);
            score.setConsultScore(newConsultScore);
            BigDecimal averageScore = (newProductScore.add(newLogisticsScore).add(newAfterSaleScore).add(newConsultScore)).divide(BigDecimal.valueOf(4), 2, RoundingMode.DOWN);
            score.setAverageScore(averageScore);
            update(score, Wrappers.<ShopScore>lambdaUpdate().eq(ShopScore::getShopId, dto.getShopId()));
            //更新店铺表分数
            H2ShopBase h2ShopBase = new H2ShopBase();
            h2ShopBase.setId(dto.getShopId());
            h2ShopBase.setMark(averageScore);
            h2ShopBaseMapper.updateById(h2ShopBase);
        }
    }

    @Override
    public ShopScoreVO queryMark(Long shopId) {
        ShopScoreVO shopScoreVO = new ShopScoreVO();
        ShopScore score = baseMapper.selectOne(Wrappers.<ShopScore>lambdaQuery().eq(ShopScore::getShopId, shopId));
        if(score == null){
            shopScoreVO.setShopId(shopId);
            return shopScoreVO;
        }
        BeanUtils.copyProperties(score, shopScoreVO);
        //计算超越同行百分比
        List<ShopScore> allShopScores = baseMapper.selectList(Wrappers.query());
        BigDecimal averageProductScore = allShopScores.stream().map(ShopScore::getProductScore).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(allShopScores.size()), 2, RoundingMode.DOWN);
        BigDecimal averageLogisticsScore = allShopScores.stream().map(ShopScore::getLogisticsScore).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(allShopScores.size()), 2, RoundingMode.DOWN);
        BigDecimal averageAfterSaleScore = allShopScores.stream().map(ShopScore::getAfterSaleScore).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(allShopScores.size()), 2, RoundingMode.DOWN);
        BigDecimal averageConsultScore = allShopScores.stream().map(ShopScore::getConsultScore).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(allShopScores.size()), 2, RoundingMode.DOWN);

        BigDecimal decimal1 = shopScoreVO.getProductScore().equals(BigDecimal.ZERO)? BigDecimal.ONE : BigDecimal.ONE.subtract(averageProductScore.divide(shopScoreVO.getProductScore(), 2, RoundingMode.DOWN));
        BigDecimal decimal2 = shopScoreVO.getLogisticsScore().equals(BigDecimal.ZERO)? BigDecimal.ONE : BigDecimal.ONE.subtract(averageLogisticsScore.divide(shopScoreVO.getLogisticsScore(), 2, RoundingMode.DOWN));
        BigDecimal decimal3 = shopScoreVO.getAfterSaleScore().equals(BigDecimal.ZERO)? BigDecimal.ONE : BigDecimal.ONE.subtract(averageAfterSaleScore.divide(shopScoreVO.getAfterSaleScore(), 2, RoundingMode.DOWN));
        BigDecimal decimal4 = shopScoreVO.getConsultScore().equals(BigDecimal.ZERO)? BigDecimal.ONE : BigDecimal.ONE.subtract(averageConsultScore.divide(shopScoreVO.getConsultScore(), 2, RoundingMode.DOWN));

        shopScoreVO.setProductScoreExceed(decimal1);
        shopScoreVO.setLogisticsScoreExceed(decimal2);
        shopScoreVO.setAfterSaleScoreExceed(decimal3);
        shopScoreVO.setConsultScoreExceed(decimal4);

        return shopScoreVO;
    }


}

